import { datatype } from "faker";
import NumberCalc from "../../logic/tools/calculator";
import "jquery.easyui";

export interface GameConfig {
    /**
     * 游戏进度回调
     * @param sign 0:结束游戏 1:开始游戏
     */
    processCallback: (sign: number) => void;
    /**
     * 渲染时间计时器回调处理
     * @param minute 分钟
     * @param second 秒
     * @param millisecond 毫秒
     */
    drawTimerCallback: (minute: number, second: number, millisecond: number) => void;
    /**
     * 渲染游戏图标回调处理
     * @param tables 游戏图表配置
     */
    drawTableCallback: (tables: number[][]) => void;
    /**
     * 通知回调
     * @param sign 0:游戏完成 1:游戏失败 2:操作警告
     * @param message 通知内容
     */
    notifyCallback: (sign: number, message: string) => void;
}
/** 游戏对象 */
export class Game {
    private readonly config: GameConfig;

    constructor(config: GameConfig) {
        this.config = config;
    }

    private x: number;
    private y: number;
    public ReConfigXY(x: number, y: number) {
        this.x = x;
        this.y = y;
    }

    public SelectItem(item: number):boolean {
        let self = this;
        if (self.timer_interval_sign === null) {
            self.config.notifyCallback(2, "请点击开始, 进行游戏");
            return false;
        }
        let value = NumberCalc.Add(self.sign, 1);
        if (value !== item) {
            self.config.notifyCallback(2, "点击错误");
            return false;
        }
        self.sign = value;
        if (self.sign === self.result) {
            self.config.notifyCallback(0, "挑战成功");
            self.End();
        }
        return true;
    }

    private minute: number = 0;
    private second: number = 0;
    private millisecond: number = 0;
    private sign: number;
    private result: number;
    private timer_interval_sign: number = null;
    /** 开始游戏 */
    public Start() {
        let self = this;

        self.MakeZeroResult();

        const interval: number = 100;
        self.timer_interval_sign = setInterval(function() {
            self.millisecond = NumberCalc.Add(self.millisecond, interval);

            let value = parseInt(NumberCalc.Div(self.millisecond, 1000).toString());
            self.second = NumberCalc.Add(self.second, value);
            self.millisecond %= 1000;

            value = parseInt(NumberCalc.Div(self.second, 60).toString());
            self.minute = NumberCalc.Add(self.minute, value);
            self.second %= 60;

            self.config.drawTimerCallback(self.minute, self.second, self.millisecond);
        }, interval);
        self.config.processCallback(1);
    }
    /** 重新渲染游戏图表 */
    public ReDrawTables() {
        let self = this;
        self.End();

        self.MakeZeroResult();

        let tables = self.GenerateTables(self.x, self.y);
        let size = datatype.number({ min: 10, max: 20 });
        tables = self.DisturbanceTables(tables, size);
        self.config.drawTableCallback(tables);
    }
    /** 归零结果 */
    private MakeZeroResult() {
        let self = this;

        self.minute = 0;
        self.second = 0;
        self.millisecond = 0;
        self.config.drawTimerCallback(self.minute, self.second, self.millisecond);
        self.sign = 0;
        self.result = NumberCalc.Mul(self.x, self.y);
    }
    /** 结束游戏 */
    public End() {
        let self = this;
        clearInterval(self.timer_interval_sign);
        self.timer_interval_sign = null;
        self.config.processCallback(0);
    }

    /**
     * 生成表格
     * @param x 横向列数
     * @param y 纵向行数
     * @returns 表格数据
     */
    public GenerateTables(x: number, y: number): number[][] {
        let list: number[][] = [];
        let number = 0;
        for (let y_index = 0; y_index < y; y_index++) {
            let arr = [];
            for (let x_index = 0; x_index < x; x_index++) {
                arr.push(++number);
            }
            list.push(arr);
        }
        return list;
    }

    /**
     * 打乱表格顺序
     * @param list 表格数据
     * @param size 打乱次序
     * @returns 结果表格数据
     */
    public DisturbanceTables(list: number[][], size: number): number[][] {
        let self = this;
        for (let index = 0; index < size; index++) {
            let coordinate_1 = self.get_table_random_position(list);
            let coordinate_2 = self.get_table_random_position(list);
            let value = list[coordinate_1.y][coordinate_1.x];
            list[coordinate_1.y][coordinate_1.x] = list[coordinate_2.y][coordinate_2.x];
            list[coordinate_2.y][coordinate_2.x] = value;
        }
        return list;
    }

    private get_table_random_position(list: number[][]): { x: number; y: number } {
        let y = datatype.number({ min: 0, max: list.length - 1 });
        let x = datatype.number({ min: 0, max: list[y].length - 1 });
        return { x, y };
    }

    /**
     * 获取棋盘规则配置
     * @returns
     */
    public GetIRegularChessboards(): IRegularChessboard[] {
        let arr: IRegularChessboard[] = [
            {
                x: 3, y: 3,
                scores: [
                    { name: "顶尖", max: 1.8, },
                    { name: "极好", min: 1.8, max: 2.5, },
                    { name: "好", min: 2.5, max: 3.6, },
                    { name: "正常", min: 3.6, max: 4.2, },
                    { name: "需要训练", min: 4.2, },
                ],
            },
            {
                x: 4, y: 4,
                scores: [
                    { name: "顶尖", max: 4.8, },
                    { name: "极好", min: 4.8, max: 7, },
                    { name: "好", min: 7, max: 11, },
                    { name: "正常", min: 11, max: 15, },
                    { name: "需要训练", min: 15, },
                ],
            },
            {
                x: 5, y: 5,
                scores: [
                    { name: "顶尖", max: 8.7, },
                    { name: "极好", min: 8.7, max: 14, },
                    { name: "好", min: 14, max: 18.5, },
                    { name: "正常", min: 18.5, max: 25, },
                    { name: "需要训练", min: 25, },
                ],
            },
            {
                x: 6, y: 6,
                scores: [
                    { name: "顶尖", max: 23, },
                    { name: "极好", min: 23, max: 30, },
                    { name: "好", min: 30, max: 44, },
                    { name: "正常", min: 44, max: 52, },
                    { name: "需要训练", min: 52, },
                ],
            },
            {
                x: 7, y: 7,
                scores: [
                    { name: "顶尖", max: 49, },
                    { name: "极好", min: 49, max: 74, },
                    { name: "好", min: 74, max: 88, },
                    { name: "正常", min: 88, max: 120, },
                    { name: "需要训练", min: 120, },
                ],
            },
        ];
        return arr;
    }

    public GenerateRegularChessboardScoreDescribe(config: IRegularChessboard) {
        let self = this;
        for (let score_i = 0; score_i < config.scores.length; score_i++) {
            let scores = config.scores[score_i];
            if (!scores.describe) {
                scores.describe = self.GenerateScoreDescribe(scores);
            }
            config.scores[score_i] = scores;
        }
    }
    public GenerateScoreDescribe(score: IRegularScore) {
        let self = this;
        if (!score.min && !score.max) {
            return "<无限制> : " + score.name;
        }
        if (!score.max) {
            return self.to_format_time_desc(score.min) + "以内 : " + score.name;
        }
        if (!score.min) {
            return self.to_format_time_desc(score.max) + "以上 : " + score.name;
        }
        return self.to_format_time_desc(score.min) + ' ~ '+ self.to_format_time_desc(score.max) +' : ' + score.name;
    }

    private to_format_time_desc(second: number) {
        var minute = parseInt(NumberCalc.Div(second, 60).toString());
        second = second % 60;
        var r = "";
        if (minute > 0) {
            r += minute + '分';
        }
        if (second > 0) {
            r += second + '秒';
        }
        return r;
    }
}

/** 规则棋盘 */
export interface IRegularChessboard {
    x: number;
    y: number;
    scores: IRegularScore[];
}
/** 规则评分 */
export interface IRegularScore {
    /** 最小范围对象 (秒) */
    min?: number,
    /** 最大范围对象 (秒) */
    max?: number,
    /** 评价名称 (顶尖/极好/好/正常/需要训练) */
    name: string,
    /** 描述 */
    describe?: string,
}
